package com.file.parser.socialsecurity;

import com.file.bo.ResponseData;
import com.file.bo.socialsecurity.LiaoningIndividualRecordSheet;
import com.file.bo.socialsecurity.LiaoningInsuranceParticipation;
import com.file.constant.ErrorCode;
import com.file.parser.BasePdfParser;
import com.file.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import technology.tabula.*;
import technology.tabula.detectors.SpreadsheetDetectionAlgorithm;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class LiaoningSocialSecurityPdfParser extends BasePdfParser {

    public ResponseData<String> parseLiaoNingSocialSecurityPdfToJson(String daId, String filePath) {
        log.info("parseLiaoNingSocialSecurityPdfToJson started, daId:{}", daId);
        String json = null;
        try {
            if (filePath.contains("cbzm")) {
                LiaoningInsuranceParticipation liaoNingInsuranceParticipation = parseLiaoNingInsuranceParticipation(filePath);
                json = JsonUtils.convertObjectToJson(liaoNingInsuranceParticipation);
            } else if (filePath.contains("qyd")) {
                LiaoningIndividualRecordSheet liaoNingIndividualRecordSheet = parseLiaoNingIndividualRecordSheet(filePath);
                json = JsonUtils.convertObjectToJson(liaoNingIndividualRecordSheet);
            } else {
                log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseLiaoNingSocialSecurityPdfToJson failed, new type not supported");
                return new ResponseData<>(null, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
            }
        } catch (Exception e) {
            log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseLiaoNingSocialSecurityPdfToJson failed", e);
            return new ResponseData<>(null, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
        }

        log.info("parseLiaoNingSocialSecurityPdfToJson completed, daId:{}", daId);
        return new ResponseData<>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
    }

    private LiaoningInsuranceParticipation parseLiaoNingInsuranceParticipation (String filePath) {  //NOSONAR

        return new LiaoningInsuranceParticipation();
    }


    private Map<Integer, List<List<String>>> parseFileToRowList (String filePath) {
        // 1. 读取文件
        File pdf = new File(filePath);

        //页面所有table的记录，每一个元素代表下面一条记录cellList
        Map<Integer, List<List<String>>> rowMap = new HashMap<>();

        // 2. pdfbox读取PDDocument
        try (PDDocument pdfDocument = PDDocument.load(pdf)) {
            // 3. tabula新建ObjectExtractor和NurminenDetectionAlgorithm，同时准备接收表格Rectangle的结构
            ObjectExtractor objectExtractor = new ObjectExtractor(pdfDocument);
            SpreadsheetDetectionAlgorithm detectionAlgorithm = new SpreadsheetDetectionAlgorithm();
            Map<Integer, List<Rectangle>> pageNumber2RectangleListMap = new HashMap<>();//key为页的序号， value为对应的Rectangle的list

            // 4. 获取每页的PageIterator
            PageIterator pageIterator = objectExtractor.extract();

            // 5. 解析每页的Rectangle
            // 如果单页pdf中有多个Rectangle，则解析出来的List<Rectangle>会有多个对象
            while (pageIterator.hasNext()) {
                Page page = pageIterator.next();
                List<Rectangle> rectangleList = detectionAlgorithm.detect(page);
                if (rectangleList.size() > 0) {
                    pageNumber2RectangleListMap.put(page.getPageNumber(), rectangleList);
                }
            }

            // 6.通过table位置获取表格具体内容
            SpreadsheetExtractionAlgorithm extractionAlgorithm = new SpreadsheetExtractionAlgorithm();

            // 如果单页pdf中有多个表格，则解析出来的List<Rectangle>会有多个对象
            for (Map.Entry<Integer, List<Rectangle>> entry : pageNumber2RectangleListMap.entrySet()) {
                List<List<String>> rowList = new ArrayList<>();
                Page page = objectExtractor.extract(entry.getKey());

                List<Rectangle> rectangleList = entry.getValue();
                for (Rectangle rectangle : rectangleList) {
                    if (Double.compare(rectangle.getHeight(), 0.0) == 0) {
                        continue;
                    }
                    rectangle.setBottom(rectangle.getBottom() + 10);
                    Page area = page.getArea(rectangle);
                    // 如果每页有多个表格，解析每一个table
                    List<Table> tableList = extractionAlgorithm.extract(area);
                    for (Table table : tableList) {
                        for (int i = 0; i < table.getRowCount(); i++) {
                            List<String> cellList = new ArrayList<>();//一条记录，每个单元格占一个元素
                            for (int j = 0; j < table.getColCount(); j++) {
                                cellList.add(table.getCell(i, j).getText(false));
                            }
                            rowList.add(cellList);
                        }
                    }
                    rowMap.put(page.getPageNumber(), rowList);
                }

            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        return rowMap;
    }

    private LiaoningIndividualRecordSheet parseLiaoNingIndividualRecordSheet (String filePath) {
        LiaoningIndividualRecordSheet liaoNingIndividualRecordSheet = parseIndividualRecordSheetHeader(filePath);
        Map<Integer, List<List<String>>> rowMap = parseFileToRowList(filePath);
        parseListToBO(rowMap, liaoNingIndividualRecordSheet);

        return liaoNingIndividualRecordSheet;
    }

    private LiaoningIndividualRecordSheet parseIndividualRecordSheetHeader (String filePath) {
        LiaoningIndividualRecordSheet liaoNingIndividualRecordSheet = new LiaoningIndividualRecordSheet();
        String pdfHeader = getPdfTextByStripper(filePath);
        pdfHeader = pdfHeader.replace(System.getProperty("line.separator", "\n"), "");

        LiaoningIndividualRecordSheet.PersonalInformation personalInformation = new LiaoningIndividualRecordSheet.PersonalInformation();
        String name = pdfHeader.substring(pdfHeader.indexOf("姓名") + 2, pdfHeader.indexOf("证件类型")).trim();
        personalInformation.setName(name);
        String idType = pdfHeader.substring(pdfHeader.indexOf("证件类型") + 4, pdfHeader.indexOf("证件号码")).trim();
        personalInformation.setIdType(idType);
        String idNo = pdfHeader.substring(pdfHeader.indexOf("证件号码") + 4, pdfHeader.indexOf("企业职工养老保险参保时间")).trim();
        personalInformation.setIdNo(idNo);
        String enterpriseWorkPensionInsurancePeriod = pdfHeader.substring(pdfHeader.indexOf("企业职工养老保险参保时间") + 12, pdfHeader.indexOf("机关事业养老保险参保时间")).trim();
        personalInformation.setEnterpriseWorkPensionInsurancePeriod(enterpriseWorkPensionInsurancePeriod);
        String causeWorkPensionInsurancePeriod = pdfHeader.substring(pdfHeader.indexOf("机关事业养老保险参保时间") + 12, pdfHeader.indexOf("城乡居民养老保险参保时间")).trim();
        personalInformation.setCauseWorkPensionInsurancePeriod(causeWorkPensionInsurancePeriod);
        String urbanResidentsPensionInsurancePeriod = pdfHeader.substring(pdfHeader.indexOf("城乡居民养老保险参保时间") + 12, pdfHeader.indexOf("工伤保险参保时间")).trim();
        personalInformation.setUrbanResidentsPensionInsurancePeriod(urbanResidentsPensionInsurancePeriod);
        String injuryInsuranceInsurancePeriod = pdfHeader.substring(pdfHeader.indexOf("工伤保险参保时间") + 8, pdfHeader.indexOf("失业保险参保时间")).trim();
        personalInformation.setInjuryInsuranceInsurancePeriod(injuryInsuranceInsurancePeriod);
        String unemploymentInsurancePeriod = pdfHeader.substring(pdfHeader.indexOf("失业保险参保时间") + 8, pdfHeader.indexOf("年度个人缴费情况") - 4).trim();
        personalInformation.setUnemploymentInsurancePeriod(unemploymentInsurancePeriod);
        liaoNingIndividualRecordSheet.setPersonalInformation(personalInformation);
        String tips = pdfHeader.substring(pdfHeader.indexOf("温馨提示：") + 5, pdfHeader.indexOf("打印时间：")).trim();
        liaoNingIndividualRecordSheet.setTips(tips);
        String printTime = pdfHeader.substring(pdfHeader.indexOf("打印时间：") + 5, pdfHeader.indexOf("您可以使用手机扫")).trim();
        liaoNingIndividualRecordSheet.setPrintTime(printTime);
        String recordPeriod = pdfHeader.substring(pdfHeader.indexOf("年度个人缴费情况") - 4, pdfHeader.indexOf("年度个人缴费情况")).trim();
        liaoNingIndividualRecordSheet.setRecordPeriod(recordPeriod);

        return liaoNingIndividualRecordSheet;
    }

    private void parseListToBO(Map<Integer, List<List<String>>> rowMap, LiaoningIndividualRecordSheet liaoNingIndividualRecordSheet) {
        String sectionName = "";
        LiaoningIndividualRecordSheet.PersonalPaymentRecordsOfYear personalPaymentRecordsOfYear = new LiaoningIndividualRecordSheet.PersonalPaymentRecordsOfYear();
        LiaoningIndividualRecordSheet.EnterpriseWorkPension enterpriseWorkPension = new LiaoningIndividualRecordSheet.EnterpriseWorkPension();
        LiaoningIndividualRecordSheet.CauseWorkPension causeWorkPension = new LiaoningIndividualRecordSheet.CauseWorkPension();
        LiaoningIndividualRecordSheet.UrbanResidentsPension urbanResidentsPension = new LiaoningIndividualRecordSheet.UrbanResidentsPension();
        LiaoningIndividualRecordSheet.InjuryInsurance injuryInsurance = new LiaoningIndividualRecordSheet.InjuryInsurance();
        LiaoningIndividualRecordSheet.UnemploymentInsurance unemploymentInsurance = new LiaoningIndividualRecordSheet.UnemploymentInsurance();
        LiaoningIndividualRecordSheet.PersonalAccountAccumulate personalAccountAccumulate = new LiaoningIndividualRecordSheet.PersonalAccountAccumulate();


        // 解析pdf第一页的表格
        for (int i = 0; i < rowMap.get(1).size(); i++) {
            List<String> cellList = rowMap.get(1).get(i);
            if (StringUtils.equals(cellList.get(0), "企业职工养老保险")) {
                sectionName = "企业职工养老保险";
                continue;
            } else if (StringUtils.equalsAny(cellList.get(0), "工伤保险")) {
                sectionName = "工伤保险";
                continue;
            } else if (StringUtils.equalsAny(cellList.get(0), "失业保险")) {
                sectionName = "失业保险";
                continue;
            } else if (StringUtils.equalsAny(cellList.get(0), "个人账户累计情况")) {
                sectionName = "个人账户累计情况";
                continue;
            }

            switch (sectionName) {//NOSONAR
                case "企业职工养老保险":
                    if (StringUtils.equalsAny(cellList.get(0), "缴费月数")) {
                        enterpriseWorkPension.setPaymentMonths(cellList.get(1));
                        causeWorkPension.setPaymentMonths(cellList.get(3));
                        urbanResidentsPension.setPaymentMonths(cellList.get(5));
                    } else if (StringUtils.equalsAny(cellList.get(0), "缴费基数金额合计")) {
                        enterpriseWorkPension.setPaymentBaseTotal(cellList.get(1));
                        causeWorkPension.setPaymentBaseTotal(cellList.get(3));
                        urbanResidentsPension.setPaymentBaseTotal(cellList.get(5));
                    } else if (StringUtils.equalsAny(cellList.get(0), "个人缴费金额合计")) {
                        enterpriseWorkPension.setPersonalPaymentBaseTotal(cellList.get(1));
                        causeWorkPension.setPersonalPaymentBaseTotal(cellList.get(3));
                        urbanResidentsPension.setPersonalPaymentBaseTotal(cellList.get(5));
                    } else if (StringUtils.equalsAny(cellList.get(0), "- -")) {
                        causeWorkPension.setPersonalPaymentBaseTotalOfWorkYear(cellList.get(3));
                    }

                    break;
                case "工伤保险":
                    injuryInsurance.setPaymentMonths(cellList.get(1));
                    injuryInsurance.setPaymentBaseTotal(cellList.get(3));
                    injuryInsurance.setPersonalPaymentBaseTotal(cellList.get(5));
                    break;
                case "失业保险":
                    if (StringUtils.equals("缴费月数", cellList.get(0))) {
                        unemploymentInsurance.setPaymentMonths(cellList.get(1));
                        unemploymentInsurance.setPaymentBaseTotal(cellList.get(3));
                        unemploymentInsurance.setPersonalPaymentBaseTotal(cellList.get(5));
                    }
                    break;
                case "个人账户累计情况":
                    if (StringUtils.equalsAny(cellList.get(0), "企业职工养老保险截至到上年度末个人账户本息合计")) {
                        personalAccountAccumulate.setEnterpriseWorkPensionBalance(cellList.get(1));
                    } else if (StringUtils.equalsAny(cellList.get(0), "机关事业养老保险截至到上年度末个人账户本息合计")) {
                        personalAccountAccumulate.setCauseWorkPensionBalance(cellList.get(1));
                    } else if (StringUtils.equalsAny(cellList.get(0), "机关事业职业年金截至到当前个人账户本息合计")) {
                        personalAccountAccumulate.setCauseWorkCareerPensionBalance(cellList.get(1));
                    } else if (StringUtils.equalsAny(cellList.get(0), "城乡居民养老年保险截至到上年度末个人账户本息合计")) {
                        personalAccountAccumulate.setUrbanResidentsPensionBalance(cellList.get(1));
                    } else if (StringUtils.equalsAny(cellList.get(0), "社会保险经办机构名称:")) {
                        personalAccountAccumulate.setSocialInsuranceAgencyName(cellList.get(1));
                    }

                    break;
                default:

            }
        }

        personalPaymentRecordsOfYear.setEnterpriseWorkPension(enterpriseWorkPension);
        personalPaymentRecordsOfYear.setCauseWorkPension(causeWorkPension);
        personalPaymentRecordsOfYear.setUrbanResidentsPension(urbanResidentsPension);
        personalPaymentRecordsOfYear.setInjuryInsurance(injuryInsurance);
        personalPaymentRecordsOfYear.setUnemploymentInsurance(unemploymentInsurance);
        liaoNingIndividualRecordSheet.setPersonalPaymentRecordsOfYear(personalPaymentRecordsOfYear);
        liaoNingIndividualRecordSheet.setPersonalAccountAccumulate(personalAccountAccumulate);
    }

    public static void main(String[] args) {
        String filePath = "D:\\data\\file\\辽宁\\zd4akdkf1769533421859319808\\app-gjzwfw-dzsb_qyd.pdf";
        String json;
        LiaoningSocialSecurityPdfParser liaoningSocialSecurityPdfParser = new LiaoningSocialSecurityPdfParser();
        json = liaoningSocialSecurityPdfParser.parseLiaoNingSocialSecurityPdfToJson("daId", filePath).getData();
        System.out.println(json);
    }
}
